<?php

class GetItemType {

}

class CalendarItemType{

}

class BodyType{

}

class NonEmptyArrayOfAllItemsType{

}

class CreateItemType {

}

class DistinguishedFolderIdType{

}

class TargetFolderIdType{

}

class CreateItemResponseType{

}

class FindItemType{

}

class FindItemResponseType{

}

class GetItemResponseType{

}

class ItemChangeType {

}

class ItemIdType {

}

class NonEmptyArrayOfItemChangeDescriptionsType {

}

class NonEmpyArrayOfItemChangesType {

}

class UpdateItemResponseType{

}

class SetItemFieldType {

}

class UpdateItemType {

}
class BasePathToElementType {

}
class PathToUnindexedFieldType extends BasePathToElementType {

}

class UnindexedFieldType {

}

class FieldURIType {

}

class UnindexedFieldURIType {

}
class NTMLSoapClient extends SoapClient {
	function __doRequest($request, $location, $action, $version) {
		$operations = explode("/",$action);
		/* Modify the request for each operation */
		switch($operations[count($operations)-1]){
			case "UpdateItem":
				$request = str_replace("xsi:type=\"ns1:PathToUnindexedFieldType\"", '', $request);
				$request = str_replace("Path", 'FieldURI', $request);
				break;
			case "FindItem":
				$str = "<ns2:ParentFolderIds>
						  <ns1:DistinguishedFolderId Id=\"calendar\"/>
						  </ns2:ParentFolderIds>
						 </ns2:FindItem>";
				$request = str_replace("</ns2:FindItem>", $str, $request);
				break;
			default:
				break;
		};
		$headers = array(
			'Method: POST',
			'Connection: Keep-Alive',
			'User-Agent: PHP-SOAP-CURL',
			'Content-Type: text/xml; charset=utf-8',
			'SOAPAction: "'.$action.'"',
		);

		$this->__last_request_headers = $headers;
		$ch = curl_init($location);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
		curl_setopt($ch, CURLOPT_POST, true );
		curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
		curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
		curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
		curl_setopt($ch, CURLOPT_USERPWD, $this->ex_account['user'] .':' . $this->ex_account['password']);
		$response = curl_exec($ch);
		curl_close($ch);
		return $response;
	}

	function __getLastRequestHeaders() {
		return implode("\n", $this->__last_request_headers)."\n";
	}


}
/**
 * Class that handle soap request and authentication
 *
 * @package LSAMPGROUP-RAC1031451
 *
 */
class MyNTMLSoapClient extends NTMLSoapClient{
	/**
	 * The exchange user account
	 *
	 * @var array $ex_account
	 */
	protected $ex_account = array(
		'user' => '',
		'password' => ''
	);
	/**
	 * The customer user id
	 *
	 * @var number $cId
	 */
	protected $cId;

	/**
	 * Set the exchange user account
	 *
	 * @param string $login
	 * @param string $password
	 */
	public function set_profile($login, $password){
		$this->ex_account['user'] = $login;
		$this->ex_account['password'] = $password;
	}

	/**
	 * Get corresponding exchange user account of the customer
	 *
	 * @param number $cId
	 */
	public function get_profile_from_cid($cId){

	}

	/**
	 * Find the newest appointment of the specified exchange account
	 *
	 * @param int $maxNumber maximum returned entries
	 * @param string $errcode the returned SOAP error code
	 * @param string $error the returned SOAP error message
	 * @return an array of Appointment objects
	 */
	public function find_newest_appointments($maxNumber, &$errcode, &$error){
		$appointments = array();
		// create the GetItem request
		$findItemRequest = new FindItemType();
		$findItemRequest->Traversal = 'Shallow'; // Shallow, Softdeleted

		// construct the ItemShape of the findItemRequest object
		$findItemRequest->ItemShape->BaseShape = 'AllProperties'; // IdOnly,
		$findItemRequest->ItemShape->BodyType = 'Best'; // Best, HTML, Text

		// construct the CalendarView
		$findItemRequest->CalendarView->StartDate = date('Y-m-d\TH:i:s');
		$findItemRequest->CalendarView->EndDate = (date('Y')+ 2) . '-01-01T00:00:00';
		$findItemRequest->CalendarView->MaxEntriesReturned = $maxNumber;
		
		// construct the parentFolderId
	    //$findItemRequest->ParentFolderIds->DistinguishedFolderId[0]->Id = 'calendar';
		try{
		    // Send the request and get the response.
		    $findItemResponse = new FindItemResponseType();
		    $findItemResponse = $this->FindItem(new SoapParam($findItemRequest, 'FindItemType'));
		   // Get response information and display
		    $findItemResponseMessage = $findItemResponse->ResponseMessages->FindItemResponseMessage;
		    $errcode = $findItemResponseMessage->ResponseCode;
		    $error = $findItemResponseMessage->MessageText;
		    //$html .= "Response Class: " . $findItemResponseMessage->ResponseClass . "<br>";
			$itemInfos = $findItemResponseMessage->RootFolder->Items->CalendarItem;
			if(count($itemInfos) > 1){
			  	foreach($itemInfos as $itemInfo){
			  		$appointment = $this->covert_calendaritem_appointment($itemInfo);
			    	array_push($appointments, $appointment);
			   	}
			}elseif (count($itemInfos) == 1){
				$appointment = $this->covert_calendaritem_appointment($itemInfos);
			    array_push($appointments, $appointment);
			}
		   	return $appointments;
		 }catch(SoapFault $e){
			$error = $e->getMessage();
			$errcode = $e->getCode();
		 }/*catch(Exception $e){
		 	var_dump($this->__getLastRequest());
        	var_dump($this->__getLastResponse());
        	return NULL;
		 }*/;
	}

	/**
	 * Get an appointment based on it's id
	 *
	 * @param string $id
	 * @param string $errcode the returned SOAP error code
	 * @param string $error the returned SOAP error message
	 * @return an Appointment object
	 */
	public function get_appointment($id, &$errcode, &$error){
		$appointments = array();
		$getItemRequest = new GetItemType();
		$getItemRequest->ItemShape->BaseShape = 'AllProperties'; // IdOnly,
		$getItemRequest->ItemShape->IncludeMimeContent = 'true';
		$getItemRequest->ItemShape->BodyType = 'Best'; // Best, HTML, Text
		$getItemRequest->ItemIds->ItemId[0]->Id = $id;
		try{
		    // Send the request and get the response.
		    $getItemResponse = new GetItemResponseType();
		    $getItemResponse = $this->GetItem(new SoapParam($getItemRequest, 'GetItemType'));
			// Get response information and display

		    $itemInfo = $getItemResponse->ResponseMessages->GetItemResponseMessage;
		    $errcode= $itemInfo->ResponseCode;
			$error= $itemInfo->MessageText;
		    $item = $itemInfo->Items->CalendarItem;
		    $appointment = $this->covert_calendaritem_appointment($item);
		    return $appointment;
		}catch(SoapFault $e){
			$error = $e->getMessage();
			$errcode = $e->getCode();
			return NULL;
		};
	}

	/**
	 * Add a new appointment
	 *
	 * @param Appointment $appointment
	 * @param string $errcode the returned SOAP error code
	 * @param string $error the returned SOAP error message
	 * @return the id of the new appointment if success or NULL if fail to add the new appointment
	 */
	public function add_appointment($appointment, &$errcode, &$error){
		$calendarItem = new CalendarItemType();
		$calendarItem->Body = new BodyType();
	    $calendarItem->Body->BodyType = "Text";
	    $calendarItem->Body->_ = $appointment->get_desc();
	    $calendarItem->Categories->String = $appointment->get_categories();
	    $calendarItem->Importance = "Normal";
	    $calendarItem->Location = $appointment->get_location();
	    $calendarItem->ImportanceSpecified = true;
	    $calendarItem->ItemClass = "IPM.Appointment";
	    $calendarItem->Subject = $appointment->get_subject();
	    // Add calendar properties to the $appointment->
	    $calendarItem->Start = $appointment->get_start_datetime();
	    $calendarItem->StartSpecified = true;
	    $calendarItem->End = $appointment->get_end_datetime();
	    $calendarItem->EndSpecified = true;
		$arrayOfItems = new NonEmptyArrayOfAllItemsType();
	  	$arrayOfItems->CalendarItem[0] = $calendarItem;

	  	$createItemRequest->SendMeetingInvitations = "SendToNone";
	    $createItemRequest->SendMeetingInvitationsSpecified = true;

	    // Add the destination folder to the CreateItem request.
	    $folder = new DistinguishedFolderIdType();
	    $folder->Id = "calendar";
	    $createItemRequest->SavedItemFolderId = new TargetFolderIdType();
	    $createItemRequest->SavedItemFolderId->DistinguishedFolderId = $folder;
	    // Add the items to the CreateItem request.
	    $createItemRequest->Items = $arrayOfItems;
		try{
		    // Send the request and get the response.
		    $createItemResponse = new CreateItemResponseType();
		    $createItemResponse = $this->CreateItem(new SoapParam($createItemRequest, 'CreateItemType'));
			$itemInfo = $createItemResponse->ResponseMessages->CreateItemResponseMessage;
		 	$errcode = $itemInfo->ResponseCode ;
		 	$error = $itemInfo->MessageText;
		    return $itemInfo->Items->CalendarItem->ItemId->Id;

		}catch(SoapFault $e){
			$error = $e->getMessage();
			$errcode = $e->getCode();
			return NULL;
		};

	}
 	/**
 	 *  Update a new appointment
	 *
	 * @param Appointment $appointment
	 * @param string $errcode the returned SOAP error code
	 * @param string $error the returned SOAP error message
	 * @return the id of the new appointment if success or NULL if fail to add the new appointment
	 */
	public function update_appointment($appointment, &$errcode, &$error){

	    $updateItemRequest = new UpdateItemType();
	    $updateItemRequest->ConflictResolution = "AutoResolve";

	    $changeType = new ItemChangeType();
		$updateItemRequest->ItemChanges[0] = $changeType;

	    // Get the ID and change key from the contact item that you btained by using FindItem or CreateItem.
	    $itemId = new ItemIdType();
	    $itemId->Id = $appointment->get_id();
	    $itemId->ChangeKey = $appointment->get_changekey();
	    $changeType->ItemId= $itemId;


	    // Update the Categories
	    $setItem = new SetItemFieldType();
	    $path = new PathToUnindexedFieldType();
	    $path->FieldURI = "item:Categories";
	    $setItem->Path = new SoapVar($path, SOAP_ENC_OBJECT, 'PathToUnindexedFieldType', 'http://schemas.microsoft.com/exchange/services/2006/types');
	    $calendarItem = new CalendarItemType();
		$calendarItem->Categories->String = $appointment->get_categories();
	    $setItem->CalendarItem = $calendarItem;
	    $changeType->Updates->SetItemField[0] = $setItem;

	    // Update the Location
	    $setItem = new SetItemFieldType();
	    $path = new PathToUnindexedFieldType();
	    $path->FieldURI = "calendar:Location";
	    $setItem->Path = new SoapVar($path, SOAP_ENC_OBJECT, 'PathToUnindexedFieldType', 'http://schemas.microsoft.com/exchange/services/2006/types');
	    $calendarItem = new CalendarItemType();
		$calendarItem->Location = $appointment->get_location();
	    $setItem->CalendarItem = $calendarItem;
	    $changeType->Updates->SetItemField[1] = $setItem;

	    // Update the Subject
	    $setItem = new SetItemFieldType();
	    $path = new PathToUnindexedFieldType();
	    $path->FieldURI = "item:Subject";
	    $setItem->Path = new SoapVar($path, SOAP_ENC_OBJECT, 'PathToUnindexedFieldType', 'http://schemas.microsoft.com/exchange/services/2006/types');
	    $calendarItem = new CalendarItemType();
		$calendarItem->Subject = $appointment->get_subject();
	    $setItem->CalendarItem = $calendarItem;
	    $changeType->Updates->SetItemField[2] = $setItem;

	    // Update the Start datetime
	    $setItem = new SetItemFieldType();
	    $path = new PathToUnindexedFieldType();
	    $path->FieldURI = "calendar:Start";
	    $setItem->Path = new SoapVar($path, SOAP_ENC_OBJECT, 'PathToUnindexedFieldType', 'http://schemas.microsoft.com/exchange/services/2006/types');
	    $calendarItem = new CalendarItemType();
		$calendarItem->Start = $appointment->get_start_datetime();
	    $setItem->CalendarItem = $calendarItem;
	    $changeType->Updates->SetItemField[3] = $setItem;

	    // Update the End datetime
	    $setItem = new SetItemFieldType();
	    $path = new PathToUnindexedFieldType();
	    $path->FieldURI = "calendar:End";
	    $setItem->Path = new SoapVar($path, SOAP_ENC_OBJECT, 'PathToUnindexedFieldType', 'http://schemas.microsoft.com/exchange/services/2006/types');
	    $calendarItem = new CalendarItemType();
		$calendarItem->End = $appointment->get_end_datetime();
	    $setItem->CalendarItem = $calendarItem;
	    $changeType->Updates->SetItemField[4] = $setItem;

	     // Update the desciption message
	    $setItem = new SetItemFieldType();
	    $path = new PathToUnindexedFieldType();
	    $path->FieldURI = "item:Body";
	    $setItem->Path = new SoapVar($path, SOAP_ENC_OBJECT, 'PathToUnindexedFieldType', 'http://schemas.microsoft.com/exchange/services/2006/types');
	    $calendarItem = new CalendarItemType();
		$calendarItem->Body = new BodyType();
	    $calendarItem->Body->BodyType = "Text";
	    $calendarItem->Body->_ = $appointment->get_desc();
	    $setItem->CalendarItem = $calendarItem;
	    $changeType->Updates->SetItemField[5] = $setItem;

	    $updateItemRequest->ItemChanges[0] = $changeType;
	    $updateItemRequest->SendMeetingInvitationsOrCancellations = 'SendToNone';
	    try{
		    // Send the request and get the response.
		    $updateItemResponse = new UpdateItemResponseType();
		    $updateItemResponse = $this->UpdateItem($updateItemRequest);
		    $itemInfo = $updateItemResponse->ResponseMessages->UpdateItemResponseMessage;
		 	$errcode = $itemInfo->ResponseCode ;
		 	$error = $itemInfo->MessageText;
			return $itemInfo->Items->CalendarItem->ItemId->Id;
		}catch(SoapFault $e){
			$error = $e->getMessage();
			$errcode = $e->getCode();
			return NULL;
		}

	}
	/**
	 * Convert a CalendarItem object to an Appointment object
	 *
	 * @param CalendarItem $itemInfo
	 * @return an Appointment object
	 */
	public function covert_calendaritem_appointment($itemInfo){
		$appointment = new Appointment();
		$appointment->set_id($itemInfo->ItemId->Id);
		$appointment->set_changekey($itemInfo->ItemId->ChangeKey);
		$appointment->set_desc($itemInfo->Body->_);
		if(is_array($itemInfo->Categories->String)){
			$appointment->set_categories($itemInfo->Categories->String);
		}else{
			$appointment->add_category($itemInfo->Categories->String);
		}

		$appointment->set_start_datetime($itemInfo->Start);
		$appointment->set_end_datetime($itemInfo->End);
		$appointment->set_subject($itemInfo->Subject);
		$appointment->set_location($itemInfo->Location);
		return $appointment;
	}
}

/**
 * Class that model appointments
 *
 * @property string $subject the appointment subject
 * @property string $start the start datetime
 * @property string $end the end datetime
 * @property string $desc the appointment description
 * @property array	$categories the appointment categories
 * @property number $cId the customer Id
 *
 */
class Appointment {
	protected $start;
	protected $end;
	protected $desc;
	protected $categories = array();
	protected $id;
	protected $subject;
	// 12-11-2008 Add location property
	protected $location;
	// 19-11-2008 Add changekey property
	protected $changekey;


	public function __contruct(){

	}

	public function get_start_datetime(){
		return $this->start;
	}

	public function set_start_datetime($datetime){
		$this->start = $datetime;
	}

	public function get_end_datetime(){
		return $this->end;
	}

	public function set_end_datetime($datetime){
		$this->end = $datetime;
	}

	public function get_desc(){
		return $this->desc;
	}

	public function set_desc($desc){
		$this->desc = $desc;
	}

	public function get_subject(){
		return $this->subject;
	}

	public function set_subject($subject){
		$this->subject = $subject;
	}

	public function add_category($category){
		array_push($this->categories, $category);
	}

	public function get_category($index){
		if(isset($this->categories[$index])){
			return $this->categories[$index];
		}else{
			return NULL;
		}
	}
	public function set_categories($categories){
		$this->categories = array();
		$this->categories = $categories;

	}

	public function get_categories(){
		return $this->categories;
	}

	public function get_id(){
		return $this->id;
	}
	public function set_id($id){
		$this->id = $id;
	}

	public function get_changekey(){
		return $this->changekey;
	}

	public function set_changekey($changekey){
		$this->changekey = $changekey;
	}

	// 12-11-2008 Add location property
	public function get_location(){
		return $this->location;
	}
	public function set_location($location){
		$this->location = $location;
	}
	// 12-11-2008
	/**
	 * Display an Appointment object as a html row
	 *
	 * @param string $redirect_link the link to the detail information page of each appointment
	 * @param array $mask the mask contains 6 elements,
	 * 					  each of which is the display mask(1->display, 0->hide) for each display item(subject,description,categories,start date, end date)
	 * @return a html string
	 */
	public function display_as_row($redirect_link, $mask=array(1,1,1,1,1,1,1)){
		$html = "<tr>";
		if(isset($mask[0]) && $mask[0]==1)
		$html .= "<td>" . $this->subject . "</td>";
		if(isset($mask[1]) && $mask[1]==1)
		$html .= "<td>" . $this->desc . "</td>";
		if(isset($mask[2]) && $mask[2]==1)
		$html .= "<td>" . $this->location . "</td>";
		if(isset($mask[3]) && $mask[3]==1){
			$html .= "<td>" ;
			if(isset($this->categories)){
				$count = 0;
				foreach($this->categories as $category){
					$html .= (($count)?", ":" " ). $category;
					$count++;
				}
			}
			$html .= "</td>";
		}
		if(isset($mask[4]) && $mask[4]==1)
		$html .= "<td>" . $this->start . "</td>";
		if(isset($mask[5]) && $mask[5]==1)
		$html .= "<td>" . $this->end . "</td>";
		if(isset($mask[6]) && $mask[6]==1){
			if($redirect_link)
			$html .= "<td><a href='$redirect_link?Id=" . urlencode($this->id) . "'>Detail</a></td>";
		}
		$html.= '</tr>';
		return $html;

	}
}
?>
